#pragma once
#include "Stdafx.h"

using namespace System;

namespace Dzonny { namespace XmlKeyboard { namespace Interop {

    enum class Vk2CharAttributes : BYTE;

    /// <summary>Mapping between single Virtual Key to different characters in different shift states</summary>
    public ref class Vk2WChar
    {
    private:
        /// <summary>A pointer to unmanaged <see cref="VK_TO_WCHARS1"/> structure this instance wraps</summary>
        /// <remarks>Can point to <see cref="PVK_TO_WCHARS1"/>, <see cref="PVK_TO_WCHARS2"/>, <see cref="PVK_TO_WCHARS3"/>, <see cref="PVK_TO_WCHARS4"/>, <see cref="PVK_TO_WCHARS5"/>, <see cref="PVK_TO_WCHARS6"/>, <see cref="PVK_TO_WCHARS7"/>, <see cref="PVK_TO_WCHARS8"/>, <see cref="PVK_TO_WCHARS9"/>, or <see cref="PVK_TO_WCHARS10"/> - depends on <see cref="modifications"/>.</remarks>
        initonly PVK_TO_WCHARS1 vk2WChars;
        /// <summary>Indicates number of shift states in <see cref="vk2WChar"/></summary>
        initonly BYTE modifications;
        
        cli::array<Char>^ chars;
    internal:
        /// <summary>CTor - creates a new instance of the <see cref="Vk2WChar"/> class</summary>
        /// <param name="vk2WChars">
        /// A pointer to unmanaged <see cref="PVK_TO_WCHARS1"/> structure to wrap in a new instance.
        /// Can point to <see cref="PVK_TO_WCHARS1"/>, <see cref="PVK_TO_WCHARS2"/>, <see cref="PVK_TO_WCHARS3"/>, <see cref="PVK_TO_WCHARS4"/>, <see cref="PVK_TO_WCHARS5"/>, <see cref="PVK_TO_WCHARS6"/>, <see cref="PVK_TO_WCHARS7"/>, <see cref="PVK_TO_WCHARS8"/>, <see cref="PVK_TO_WCHARS9"/>, or <see cref="PVK_TO_WCHARS10"/> - depends on <paramref name="modifications"/>.
        /// </param>
        /// <param name="modifications">Indicates how many shift states are stored in <paramref name="vk2WChars"/>.</param>
        /// <exception cref="ArgumentNullException"><paramref name="vk2WChars"/> is null</exception>
        Vk2WChar(const PVK_TO_WCHARS1 vk2WChars, BYTE modifications);
    public:
        /// <summary>Gets Virtual Key code this mapping is for</summary>
        property BYTE VirtualKey{BYTE get();}
        /// <summary>Gets additional mapping attributes (such as CapsLock behavior)</summary>
        property Vk2CharAttributes Attributes{Vk2CharAttributes get();}
        /// <summary>Gets mapping for this key for various modifier states</summary>
        /// <remarks>
        /// In addition to regular characcters there can be special values in this array indicating special behavior.
        /// See <see cref="NoChar"/>, <see cref="Ligature"/> and <see cref="DeadChar"/>.
        /// </remarks>
        property cli::array<Char>^ Chars{cli::array<Char>^ get();}

        /// <summary>Special value for the <see cref="Chars"/> array: No character is generated by pressing this key with the current shift state.</summary>
        literal Char NoChar = WCH_NONE;
        /// <summary>
        /// Special value for the <see cref="Chars"/> array: The character is a ligature.
        /// The characters generated by this keystroke are found in <see cref="KbdTables::Ligatures"/>.
        /// </summary>
        literal Char Ligature = WCH_LGTR;
        /// <summary>
        /// Special value for the <see cref="Chars"/> array: The character is a dead-key:
        /// The next item in the <see cref="Chars"/> array contains the values of the dead characters (diaresis) that can be produced by the Virtual Key.
        /// </summary>
        literal Char DeadChar = WCH_DEAD;
    };

    /// <summary>Indicates flags for <see cref="Vk2WChar"/></summary>
    [Flags]
    public enum class Vk2CharAttributes : BYTE{
        /// <summary>Caps lock affects this key same way as Shift</summary>
        CapsLock = CAPLOK,
        /// <summary>CapsLock uppercases the unshifted char</summary>
        SgCaps = SGCAPS,
        /// <summary>Caps lock affects this key same way as Shift (for ALtGr)</summary>
        CapsLockALtGr = CAPLOKALTGR, 
        /// <summary>KANALOK</summary>
        KanaLock = KANALOK,
        /// <summary>GRPSELTAP</summary>
        GrpSelTap = GRPSELTAP
    };

}}}